#include "stdafx.h"
#include "CppUnitTest.h"
#include <exception>
#include "./../forward_list/forward_list.h"

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace UnitTest
{
	TEST_CLASS(UnitTestForwardList)
	{
	public:

		TEST_METHOD(TestListIsEmpty)
		{
			forward_list<int> l;
			Assert::AreEqual(true, l.is_empty());
		}

		TEST_METHOD(TestListPush_FrontAndFront)
		{
			forward_list<int> l;
			int i = 13;
			l.push_front(i);
			Assert::AreEqual(false, l.is_empty());		
			Assert::AreEqual(i, l.front());
		}

		TEST_METHOD(TestListClear)
		{
			forward_list<int> l;
			for (int i = 0; i < 5; i++)
			{
				l.push_front(i);
			}
			Assert::AreEqual(false, l.is_empty());
			l.clear();
			Assert::AreEqual(true, l.is_empty());
		}

		TEST_METHOD(TestListIterator)
		{
			forward_list<int> l;
			for (int i = 0; i < 5; i++)
			{
				l.push_front(i);
			}
			int i = 4;
			for (auto it = l.begin(); it != l.end(); it++)
			{
				Assert::AreEqual(i, it->data);
				i--;
			}
		}

		TEST_METHOD(TestListPop_front)
		{
			forward_list<int> l;
			int i1 = 1, i2 = 2;
			l.push_front(i1);
			l.push_front(i2);
			Assert::AreEqual(i2, l.pop_front());
			Assert::AreEqual(i1, l.pop_front());
			Assert::AreEqual(true, l.is_empty());
			try
			{
				l.pop_front();
				Assert::AreEqual(true, false);
			}
			catch (std::exception e)
			{
			}
		}

		TEST_METHOD(TestListCopyConstructor)
		{
			forward_list<int> l;
			int i1 = 1, i2 = 2;
			l.push_front(i1);
			l.push_front(i2);

			Assert::AreEqual(false, l.is_empty());
			Logger::WriteMessage("0");

			forward_list<int> l2(l);
			Logger::WriteMessage("1");
			forward_list<int>::iterator it2 = l2.begin();
			Assert::AreEqual(false, l2.is_empty());
			Logger::WriteMessage("2");
			for (auto it = l.begin(); it != l.end(); it++)
			{
				Assert::AreEqual(it->data, it2->data);
				it2++;
			}
		}

		TEST_METHOD(TestListCopyAssignment)
		{
			forward_list<int> l;
			int i1 = 1, i2 = 2;
			l.push_front(i1);
			l.push_front(i2);

			Assert::AreEqual(false, l.is_empty());

			forward_list<int> l2;
			int i3 = 3, i4 = 4;
			l2.push_front(i3);
			l2.push_front(i4);
			l2 = l;
			forward_list<int>::iterator it2 = l2.begin();
			Assert::AreEqual(false, l2.is_empty());
			for (auto it = l.begin(); it != l.end(); it++)
			{
				Assert::AreEqual(it->data, it2->data);
				it2++;
			}
		}

		TEST_METHOD(TestListInsertAfter)
		{
			forward_list<int> l;
			int i1 = 1, i2 = 2, i3 = 4;
			l.push_front(i1);
			l.push_front(i2);
			l.push_front(i3);
			for (auto it = l.begin(); it != l.end(); it++)
			{
				if (it->data == 4)
				{
					int i4 = 3;
					l.insert_after(it, i4);
				}
			}
			int i = 4;
			for (auto it = l.begin(); it != l.end(); it++)
			{
				Assert::AreEqual(i, it->data);
				i--;
			}
		}

		TEST_METHOD(TestListDeleteAfter)
		{
			forward_list<int> l;
			int i1 = 1, i2 = 10, i3 = 2;
			l.push_front(i1);
			l.push_front(i2);
			l.push_front(i3);
			for (auto it = l.begin(); it != l.end(); it++)
			{
				if (it->data == 2)
				{
					l.erase_after(it);
				}
			}
			int i = 2;
			for (auto it = l.begin(); it != l.end(); it++)
			{
				Assert::AreEqual(i, it->data);
				i--;
			}
		}

		TEST_METHOD(TestListErase)
		{
			forward_list<int> l;
			int i1 = 1, i2 = 10, i3 = 2;
			l.push_front(i1);
			l.push_front(i2);
			l.push_front(i3);
			l.erase(10);
			int i = 2;
			for (auto it = l.begin(); it != l.end(); it++)
			{
				Assert::AreEqual(i, it->data);
				i--;
			}
		}

		TEST_METHOD(TestListSwap)
		{
			forward_list<int> l;
			for (int i = 0; i < 5; i++)
			{
				l.push_front(i);
			}
			forward_list<int> l2;
			for (int i = 10; i < 40; i+=10)
			{
				l2.push_front(i);
			}
			l.swap(l2);
			int i = 30;
			for (auto it = l.begin(); it != l.end(); it++)
			{
				Assert::AreEqual(i, it->data);
				i -= 10;
			}
			i = 4;
			for (auto it = l2.begin(); it != l2.end(); it++)
			{
				Assert::AreEqual(i, it->data);
				i--;
			}
		}

		TEST_METHOD(TestListCount)
		{
			forward_list<int> l;
			int i1 = 1, i2 = 10, i3 = 2;
			l.push_front(i1);
			l.push_front(i2);
			l.push_front(i3);
			Assert::AreEqual(3, l.count());
			l.erase(10);
			Assert::AreEqual(2, l.count());
			l.pop_front();
			Assert::AreEqual(1, l.count());
			l.pop_front();
			Assert::AreEqual(0, l.count());
		}

		TEST_METHOD(TestListSort)
		{
			forward_list<int> l;
			int i1 = 1, i2 = 3, i3 = 2;
			l.push_front(i1);
			l.push_front(i2);
			l.push_front(i3);
			l.sort();
			int i = 1;
			for (auto it = l.begin(); it != l.end(); it++)
			{
				Assert::AreEqual(i, it->data);
				i++;
			}
		}
	};
}